import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class PointOfSaleTerminal {
    private Properties productCFG;
    private Map<Product, Integer> productMap = new HashMap<Product, Integer>();

    /**
     * Configure prising policy.
     * @param pricingFilePath path to property file that contains products information
     */
    public void setPricing(String pricingFilePath) {
        try {
            InputStream is = new FileInputStream(pricingFilePath);
            productCFG = new Properties();
            productCFG.load(is);
        } catch (IOException e) {
            throw new IllegalArgumentException("Sorry, properties path is wrong.");
        }
    }

    /**
     * Add product to customers cart.
     * @param productName productName
     * @throws IllegalArgumentException throws when there is no such product in main property file
     */
    public void scan(Character productName) throws IllegalArgumentException {
        Product product = getProduct(productName);
        int count = productMap.get(product) == null ? 1 : productMap.get(product) + 1;
        productMap.put(product, count);
    }

    /**
     * Add products to customers cart. Each letter in the string is the name of the product.
     * @param productName productName
     * @throws IllegalArgumentException throws when there is no such product in main property file
     */
    public void scan(String productName) throws IllegalArgumentException {
        for (int i = 0; i < productName.length(); i++) {
            Product product = getProduct(productName.charAt(i));
            int count = productMap.get(product) == null ? 1 : productMap.get(product) + 1;
            productMap.put(product, count);
        }
    }

    /**
     * Calculate total value of all products in customers cart
     * @return total products values
     */
    public BigDecimal calculateTotal() {
        double result = 0;

        for (Map.Entry<Product, Integer> productGroup : productMap.entrySet()) {
            Product product = productGroup.getKey();
            if (product.getVolumeNumber() != null) {
                result += (productGroup.getValue() / product.getVolumeNumber()) * product.getVolumePrice();
                result += (productGroup.getValue() % product.getVolumeNumber()) * product.getUnitPrice();
            } else {
                result += product.getUnitPrice() * productGroup.getValue();
            }
        }

        return BigDecimal.valueOf(result);
    }

    private Product getProduct(char productName) throws IllegalArgumentException {
        for (Product product : productMap.keySet()) {
            if (product.getName() == productName) {
                return product;
            }
        }

        String unitPriceProperty = getProperty(productName + ".unitPrice");
        if (unitPriceProperty == null) {
            throw new IllegalArgumentException("Sorry, there is no such product in property file.");
        }

        Product product = new Product();
        product.setName(productName);
        product.setUnitPrice(Double.valueOf(unitPriceProperty));

        String volumePriceProperty = getProperty(productName + ".volumePrice");
        if (volumePriceProperty != null) {
            product.setVolumePrice(Double.valueOf(volumePriceProperty));
        }

        String volumeNumberProperty = getProperty(productName + ".volumeNumber");
        if (volumeNumberProperty != null) {
            product.setVolumeNumber(Integer.valueOf(volumeNumberProperty));
        }

        return product;
    }

    private String getProperty(String propertyName) {
        String property = productCFG.getProperty(propertyName);
        if (property != null && property.isEmpty())
            return null;
        return property;
    }
}
